---
layout: "vagrant-cloud"
page_title: "Vagrant Cloud API"
sidebar_current: "vagrant-cloud-api"
---

<% content_for :head do %>
  <script type="text/javascript">
    var setExampleLanguage = function(language) {
      $(".examples-menu").removeClass("active");
      $(".examples-menu-" + language).addClass("active");
      $(".examples pre.highlight").hide();
      $(".examples pre.highlight." + language).show();
    }

    $(document).on('ready turbolinks:load', function() {
      setExampleLanguage("shell");
    });
  </script>

  <style>
    li {
      margin: 0 !important;
    }

    .examples p {
      display: none;
    }

    ul.examples-header {
      margin: 0;
      padding: 0 1em;
    }

    ul.examples-header > li {
      border: 1px solid #ccc;
      border-bottom: 0;
      border-top-left-radius: 4px;
      border-top-right-radius: 4px;
      display: inline-block;
      margin: 0 !important;
      margin-bottom: -1px !important;
      padding: 0 0.5em;
      padding-bottom: 1px;
    }

    ul.examples-header > li.active {
      background-color: #f8f8f8;
    }

    ul.examples-header > li a {
      color: #555 !important;
    }

    ul.examples-header > li a:hover {
      color: #333 !important;
      text-decoration: none !important;
    }

    .example-body {
    }
  </style>
<% end %>

# Vagrant Cloud API

## Using the API

Vagrant Cloud provides an API for users to interact with Vagrant Cloud for experimentation, automation, or building new features and tools on top of our existing application.

### Authentication

Some API endpoints require authentication to create new resources, update or delete existing resources, or to read a private resource.

Clients can authenticate using an authentication token.
The token can be passed to Vagrant Cloud one of two ways:

1. (Preferred) Set the `Authorization` header to `"Bearer "` and the value of the authentication token.
2. Pass the authentication token as an `access_token` URL parameter.

Examples below will set the header, but feel free to use whichever method is easier for your implementation.

-> The `X-Atlas-Token` header is also supported for backwards-compatibility.

### Request and Response Format

Requests to Vagrant Cloud which include data attributes (`POST` or `PUT`/`PATCH`) should set the `Content-Type` header to `"application/json"`, and include a valid JSON body with the request.

JSON responses may include an `errors` key, which will contain an array of error strings, as well as a `success` key.
For example:

```json
{
  "errors": [
    "Resource not found!"
  ],
  "success": false
}
```

### Response Codes

Vagrant Cloud may respond with the following response codes, depending on the status of the request and context:

#### Success

##### **200** OK
##### **201** Created
##### **204** No Content

#### Client Errors

##### **401** Unauthorized

You do not have authorization to access the requested resource.

##### **402** Payment Required

You are trying to access a resource which is delinquent on billing.
Please contact the owner of the resource so that they can update their billing information.

##### **403** Forbidden

You are attempting to use the system in a way which is not allowed.
There could be required request parameters that are missing, or one of the parameters is invalid.
Please check the response `errors` key, and double-check the examples below for any discrepancies.

##### **404** Not Found

The resource you are trying to access does not exist. This may also be returned if you attempt to access a private resource that you don't have authorization to view.

##### **422** Unprocessable Entity

##### **429** Too Many Requests

You are currently being rate-limited. Please decrease your frequency of usage, or contact us at [support+vagrantcloud@hashicorp.com](mailto:support+vagrantcloud@hashicorp.com) with a description of your use case so that we can consider creating an exception.

#### Server Errors

##### **500** Internal Server Error

The server failed to respond to the request for an unknown reason.
Please contact [support+vagrantcloud@hashicorp.com](mailto:support+vagrantcloud@hashicorp.com) with a description of the problem so that we can investigate.

##### **503** Service Unavailable

Vagrant Cloud is temporarily in maintenance mode.
Please check the [HashiCorp Status Site](http://status.hashicorp.com) for more information.

## Creating a usable box from scratch

-> This assumes that you have a valid Vagrant Cloud authentication token. You can [create one via the API](#create-a-token), or [create one on the Vagrant Cloud website](https://app.vagrantup.com/settings/security).

In order to create a usable box on Vagrant Cloud, perform the following steps:

1. [Create a new box](#create-a-box)
1. [Create a new version](#create-a-version)
1. [Create a new provider](#create-a-provider)
1. [Upload a box image for that provider](#upload-a-provider)
1. [Release the version](#release-a-version)

#### Example Requests

<div class="examples">
  <ul class="examples-header">
    <li class="examples-menu examples-menu-shell"><a onclick="setExampleLanguage('shell');">cURL</a></li>
    <li class="examples-menu examples-menu-ruby"><a onclick="setExampleLanguage('ruby');">Ruby</a></li>
  </ul>
  <div class="examples-body">
    ```shell
    # Create a new box
    curl \
      --header "Content-Type: application/json" \
      --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \
      https://app.vagrantup.com/api/v1/boxes \
      --data '{ "box": { "username": "myuser", "name": "test" } }'

    # Create a new version
    curl \
      --header "Content-Type: application/json" \
      --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \
      https://app.vagrantup.com/api/v1/box/myuser/test/versions \
      --data '{ "version": { "version": "1.2.3" } }'

    # Create a new provider
    curl \
      --header "Content-Type: application/json" \
      --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \
      https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3/providers \
      --data '{ "provider": { "name": "virtualbox" } }'

    # Prepare the provider for upload/get an upload URL
    response=$(curl \
      --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \
      https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3/provider/virtualbox/upload)

    # Extract the upload URL from the response (requires the jq command)
    upload_path=$(echo "$response" | jq .upload_path)

    # Perform the upload
    curl $upload_path --request PUT --upload-file virtualbox-1.2.3.box

    # Release the version
    curl \
      --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \
      https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3/release \
      --request PUT
    ```

    ```ruby
    # gem install http, or add `gem "http"` to your Gemfile
    require "http"

    api = HTTP.persistent("https://app.vagrantup.com").headers(
      "Content-Type" => "application/json",
      "Authorization" => "Bearer #{ENV['VAGRANT_CLOUD_TOKEN']}"
    )

    # Create a new box
    api.post "/api/v1/boxes",
      json: { box: { username: "myuser", name: "test" } }

    # Create a new version
    api.post "/api/v1/box/myuser/test/versions",
      json: { version: { version: "1.2.3" } }

    # Create a new provider
    api.post "/api/v1/box/myuser/test/version/1.2.3/providers",
      json: { provider: { name: "virtualbox" } }

    # Prepare the provider for upload
    response = api.get("/api/v1/box/myuser/test/version/1.2.3/provider/virtualbox/upload")

    # Extract the upload URL
    upload_path = response.parse['upload_path']

    # Upload the box image
    HTTP.put upload_path, body: File.open("virtualbox-1.2.3.box")
    
    # Release the version
    api.put("/api/v1/box/myuser/test/version/1.2.3/release")
    ```
  </div>
</div>

## Authentication

### Create a token

`POST /api/v1/authenticate`

Creates a new token for the given user.

#### Arguments

* `token`
    * `description` (Optional) - A description of the token.
* `two_factor`
    * `code` - A two-factor authentication code. Required to use this API method if 2FA is enabled. See [Request a 2FA code](#request-a-2fa-code) if not using a TOTP application.
* `user`
    * `login` - Username or email address of the user authenticating.
    * `password` - The user's password.

#### Example Request

<div class="examples">
  <ul class="examples-header">
    <li class="examples-menu examples-menu-shell"><a onclick="setExampleLanguage('shell');">cURL</a></li>
    <li class="examples-menu examples-menu-ruby"><a onclick="setExampleLanguage('ruby');">Ruby</a></li>
  </ul>
  <div class="examples-body">
    ```shell
    curl \
      --header "Content-Type: application/json" \
      https://app.vagrantup.com/api/v1/authenticate \
      --data '
        {
          "token": {
            "description": "Login from cURL"
          },
          "user": {
            "login": "myuser",
            "password": "secretpassword"
          }
        }
      '
    ```

    ```ruby
    # gem install http, or add `gem "http"` to your Gemfile
    require "http"

    api = HTTP.persistent("https://app.vagrantup.com").headers(
      "Content-Type" => "application/json"
    )

    response = api.post("/api/v1/authenticate", json: {
      token: { description: "Login from Ruby" },
      user: { login: "myuser", password: "secretpassword" }
    })

    if response.status.success?
      # Success, the response attributes are available here.
      p response.parse
    else
      # Error, inspect the `errors` key for more information.
      p response.code, response.body
    end
    ```
  </div>
</div>

#### Example Response

```json
{
  "description": "Login from cURL",
  "token": "qwlIE1qBVUafsg.atlasv1.FLwfJSSYkl49i4qZIu8R31GBnI9r8DrW4IQKMppkGq5rD264lRksTqaIN0zY9Bmy0zs",
  "token_hash": "7598236a879ecb42cb0f25399d6f25d1d2cfbbc6333392131bbdfba325eb352795c169daa4a61a8094d44afe817a857e0e5fc7dc72a1401eb434577337d1246c",
  "created_at": "2017-10-18T19:16:24.956Z"
}
```

### Validate a token

`GET /api/v1/authenticate`

Responds [`200 OK`](#200-ok) if the authentication request was successful, otherwise responds [`401 Unauthorized`](#401-unauthorized).

#### Example Request

<div class="examples">
  <ul class="examples-header">
    <li class="examples-menu examples-menu-shell"><a onclick="setExampleLanguage('shell');">cURL</a></li>
    <li class="examples-menu examples-menu-ruby"><a onclick="setExampleLanguage('ruby');">Ruby</a></li>
  </ul>
  <div class="examples-body">
    ```shell
    curl \
      --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \
      https://app.vagrantup.com/api/v1/authenticate
    ```

    ```ruby
    # gem install http, or add `gem "http"` to your Gemfile
    require "http"

    api = HTTP.persistent("https://app.vagrantup.com").headers(
      "Authorization" => "Bearer #{ENV['VAGRANT_CLOUD_TOKEN']}"
    )

    response = api.get("/api/v1/authenticate")

    if response.status.success?
      # Success, the response attributes are available here.
      p response.parse
    else
      # Error, inspect the `errors` key for more information.
      p response.code, response.body
    end
    ```
  </div>
</div>

### Delete a token

`DELETE /api/v1/authenticate`

Responds [`204 OK`](#204-no-content) if the deletion request was successful, otherwise responds [`401 Unauthorized`](#401-unauthorized).

#### Example Request

<div class="examples">
  <ul class="examples-header">
    <li class="examples-menu examples-menu-shell"><a onclick="setExampleLanguage('shell');">cURL</a></li>
    <li class="examples-menu examples-menu-ruby"><a onclick="setExampleLanguage('ruby');">Ruby</a></li>
  </ul>
  <div class="examples-body">
    ```shell
    curl \
      --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \
      --request DELETE \
      https://app.vagrantup.com/api/v1/authenticate
    ```

    ```ruby
    # gem install http, or add `gem "http"` to your Gemfile
    require "http"

    api = HTTP.persistent("https://app.vagrantup.com").headers(
      "Authorization" => "Bearer #{ENV['VAGRANT_CLOUD_TOKEN']}"
    )

    response = api.delete("/api/v1/authenticate")

    if response.status.success?
      # Success, the response attributes are available here.
      p response.parse
    else
      # Error, inspect the `errors` key for more information.
      p response.code, response.body
    end
    ```
  </div>
</div>

### Request a 2FA code

`POST /api/v1/two-factor/request-code`

Sends a 2FA code to the requested delivery method.

#### Arguments

* `two_factor`
    * `delivery_method` - A valid 2FA delivery method. Currently only `sms` is supported.
* `user`
    * `login` - Username or email address of the user authenticating.
    * `password` - The user's password.

#### Example Request

<div class="examples">
  <ul class="examples-header">
    <li class="examples-menu examples-menu-shell"><a onclick="setExampleLanguage('shell');">cURL</a></li>
    <li class="examples-menu examples-menu-ruby"><a onclick="setExampleLanguage('ruby');">Ruby</a></li>
  </ul>
  <div class="examples-body">
    ```shell
    curl \
      --header "Content-Type: application/json" \
      https://app.vagrantup.com/api/v1/authenticate \
      --data '
        {
          "two_factor": {
            "delivery_method": "sms"
          },
          "user": {
            "login": "myuser",
            "password": "secretpassword"
          }
        }
      '
    ```

    ```ruby
    # gem install http, or add `gem "http"` to your Gemfile
    require "http"

    api = HTTP.persistent("https://app.vagrantup.com").headers(
      "Content-Type" => "application/json"
    )

    response = api.post("/api/v1/two-factor/request-code", json: {
      two_factor: { delivery_method: "sms" },
      user: { login: "myuser", password: "secretpassword" }
    })

    if response.status.success?
      # Success, the response attributes are available here.
      p response.parse
    else
      # Error, inspect the `errors` key for more information.
      p response.code, response.body
    end
    ```
  </div>
</div>

#### Example Response

```json
{
  "two_factor": {
    "obfuscated_destination": "SMS number ending in 7890"
  }
}
```

## Organizations

### Read an organization

`GET /api/v1/user/:username`

#### Example Request

<div class="examples">
  <ul class="examples-header">
    <li class="examples-menu examples-menu-shell"><a onclick="setExampleLanguage('shell');">cURL</a></li>
    <li class="examples-menu examples-menu-ruby"><a onclick="setExampleLanguage('ruby');">Ruby</a></li>
  </ul>
  <div class="examples-body">
    ```shell
    curl \
      --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \
      https://app.vagrantup.com/api/v1/user/myuser
    ```

    ```ruby
    # gem install http, or add `gem "http"` to your Gemfile
    require "http"

    api = HTTP.persistent("https://app.vagrantup.com").headers(
      "Authorization" => "Bearer #{ENV['VAGRANT_CLOUD_TOKEN']}"
    )

    response = api.get("/api/v1/user/myuser")

    if response.status.success?
      # Success, the response attributes are available here.
      p response.parse
    else
      # Error, inspect the `errors` key for more information.
      p response.code, response.body
    end
    ```
  </div>
</div>

#### Example Response

```json
{
  "username": "myuser",
  "avatar_url": "https://www.gravatar.com/avatar/130a640278870c3dada38b3d912ee022?s=460&d=mm",
  "profile_html": "<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>\n",
  "profile_markdown": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
  "boxes": []
}
```

## Search

### Search for boxes

`GET /api/v1/search`

#### Arguments

* `q` - (Optional) The search query. Results will match the `username`, `name`, or `short_description` fields for a box. If omitted, the top boxes based on `sort` and `order` will be returned (defaults to "downloads desc").
* `provider` - (Optional) Filter results to boxes supporting for a specific provider.
* `sort` - (Optional, default: `"downloads"`) The field to sort results on. Can be one of `"downloads"`, `"created"`, or `"updated"`.
* `order` - (Optional, default: `"desc"`) The order to return the sorted field in. Can be `"desc"` os `"asc"`.
* `limit` - (Optional, default: `10`) The number of results to return (max of 100).
* `page` - (Optional, default: `1`)

#### Example Request

<div class="examples">
  <ul class="examples-header">
    <li class="examples-menu examples-menu-shell"><a onclick="setExampleLanguage('shell');">cURL</a></li>
    <li class="examples-menu examples-menu-ruby"><a onclick="setExampleLanguage('ruby');">Ruby</a></li>
  </ul>
  <div class="examples-body">
    ```shell
    curl \
      --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \
      https://app.vagrantup.com/api/v1/search?q=test&provider=virtualbox
    ```

    ```ruby
    # gem install http, or add `gem "http"` to your Gemfile
    require "http"

    api = HTTP.persistent("https://app.vagrantup.com").headers(
      "Authorization" => "Bearer #{ENV['VAGRANT_CLOUD_TOKEN']}"
    )

    response = api.get("/api/v1/search", params: {
      q: "test",
      provider: "virtualbox"
    })

    if response.status.success?
      # Success, the response attributes are available here.
      p response.parse
    else
      # Error, inspect the `errors` key for more information.
      p response.code, response.body
    end
    ```
  </div>
</div>

#### Example Response

```json
{
  "boxes": [
    {
      "created_at": "2017-10-20T14:19:59.842Z",
      "updated_at": "2017-10-20T15:23:53.363Z",
      "tag": "myuser/test",
      "name": "test",
      "short_description": "My dev box",
      "description_html": "<p>My development Vagrant box</p>\n",
      "username": "myuser",
      "description_markdown": "My development Vagrant box",
      "private": true,
      "downloads": 123,
      "current_version": {
        "version": "1.2.3",
        "status": "active",
        "description_html": "<p>A new version</p>\n",
        "description_markdown": "A new version",
        "created_at": "2017-10-20T15:23:17.184Z",
        "updated_at": "2017-10-20T15:23:53.355Z",
        "number": "1.2.3",
        "release_url": "https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3/release",
        "revoke_url": "https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3/revoke",
        "providers": [
          {
            "name": "virtualbox",
            "hosted": false,
            "hosted_token": null,
            "original_url": "https://example.com/virtualbox-1.2.3.box",
            "created_at": "2017-10-20T15:23:35.718Z",
            "updated_at": "2017-10-20T15:23:35.718Z",
            "download_url": "https://vagrantcloud.com/myuser/boxes/test/versions/1.2.3/providers/virtualbox.box"
          }
        ]
      }
    }
  ]
}
```

## Boxes

### Read a box

`GET /api/v1/box/:username/:name`

#### Example Request

<div class="examples">
  <ul class="examples-header">
    <li class="examples-menu examples-menu-shell"><a onclick="setExampleLanguage('shell');">cURL</a></li>
    <li class="examples-menu examples-menu-ruby"><a onclick="setExampleLanguage('ruby');">Ruby</a></li>
  </ul>
  <div class="examples-body">
    ```shell
    curl \
      --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \
      https://app.vagrantup.com/api/v1/box/myuser/test
    ```

    ```ruby
    # gem install http, or add `gem "http"` to your Gemfile
    require "http"

    api = HTTP.persistent("https://app.vagrantup.com").headers(
      "Authorization" => "Bearer #{ENV['VAGRANT_CLOUD_TOKEN']}"
    )

    response = api.get("/api/v1/box/myuser/test")

    if response.status.success?
      # Success, the response attributes are available here.
      p response.parse
    else
      # Error, inspect the `errors` key for more information.
      p response.code, response.body
    end
    ```
  </div>
</div>

#### Example Response

```json
{
  "created_at": "2017-10-20T14:19:59.842Z",
  "updated_at": "2017-10-20T15:23:53.363Z",
  "tag": "myuser/test",
  "name": "test",
  "short_description": "My dev box",
  "description_html": "<p>My development Vagrant box</p>\n",
  "username": "myuser",
  "description_markdown": "My development Vagrant box",
  "private": true,
  "downloads": 123,
  "current_version": {
    "version": "1.2.3",
    "status": "active",
    "description_html": "<p>A new version</p>\n",
    "description_markdown": "A new version",
    "created_at": "2017-10-20T15:23:17.184Z",
    "updated_at": "2017-10-20T15:23:53.355Z",
    "number": "1.2.3",
    "release_url": "https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3/release",
    "revoke_url": "https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3/revoke",
    "providers": [
      {
        "name": "virtualbox",
        "hosted": false,
        "hosted_token": null,
        "original_url": "https://example.com/virtualbox-1.2.3.box",
        "created_at": "2017-10-20T15:23:35.718Z",
        "updated_at": "2017-10-20T15:23:35.718Z",
        "download_url": "https://vagrantcloud.com/myuser/boxes/test/versions/1.2.3/providers/virtualbox.box"
      }
    ]
  },
  "versions": [
    {
      "version": "1.2.3",
      "status": "active",
      "description_html": "<p>A new version</p>\n",
      "description_markdown": "A new version",
      "created_at": "2017-10-20T15:23:17.184Z",
      "updated_at": "2017-10-20T15:23:53.355Z",
      "number": "1.2.3",
      "release_url": "https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3/release",
      "revoke_url": "https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3/revoke",
      "providers": [
        {
          "name": "virtualbox",
          "hosted": false,
          "hosted_token": null,
          "original_url": "https://example.com/virtualbox-1.2.3.box",
          "created_at": "2017-10-20T15:23:35.718Z",
          "updated_at": "2017-10-20T15:23:35.718Z",
          "download_url": "https://vagrantcloud.com/myuser/boxes/test/versions/1.2.3/providers/virtualbox.box"
        }
      ]
    }
  ]
}
```

### Create a box

`POST /api/v1/boxes`

#### Arguments

* `box`
    * `username` - The username of the organization that will own this box.
    * `name` - The name of the box.
    * `short_description` - A short summary of the box.
    * `description` - A longer description of the box. Can be formatted with [Markdown][markdown].
    * `is_private` (Optional, default: `true`) - Whether or not this box is private.

#### Example Request

<div class="examples">
  <ul class="examples-header">
    <li class="examples-menu examples-menu-shell"><a onclick="setExampleLanguage('shell');">cURL</a></li>
    <li class="examples-menu examples-menu-ruby"><a onclick="setExampleLanguage('ruby');">Ruby</a></li>
  </ul>
  <div class="examples-body">
    ```shell
    curl \
      --header "Content-Type: application/json" \
      --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \
      https://app.vagrantup.com/api/v1/boxes \
      --data '
        {
          "box": {
            "username": "myuser",
            "name": "test",
            "short_description": "My dev box",
            "description": "My development Vagrant box",
            "is_private": true
          }
        }
      '
    ```

    ```ruby
    # gem install http, or add `gem "http"` to your Gemfile
    require "http"

    api = HTTP.persistent("https://app.vagrantup.com").headers(
      "Content-Type" => "application/json",
      "Authorization" => "Bearer #{ENV['VAGRANT_CLOUD_TOKEN']}"
    )

    response = api.post("/api/v1/boxes", json: {
      box: {
        username: "myuser",
        name: "test",
        short_description: "My dev box",
        description: "My development Vagrant box",
        is_private: true
      }
    })

    if response.status.success?
      # Success, the response attributes are available here.
      p response.parse
    else
      # Error, inspect the `errors` key for more information.
      p response.code, response.body
    end
    ```
  </div>
</div>

#### Example Response

Response body is identical to [Reading a box](#read-a-box).

### Update a box

`PUT /api/v1/box/:username/:name`

#### Arguments

* `box`
    * `name` - The name of the box.
    * `short_description` - A short summary of the box.
    * `description` - A longer description of the box. Can be formatted with [Markdown](https://daringfireball.net/projects/markdown/syntax).
    * `is_private` (Optional, default: `true`) - Whether or not this box is private.

#### Example Request

<div class="examples">
  <ul class="examples-header">
    <li class="examples-menu examples-menu-shell"><a onclick="setExampleLanguage('shell');">cURL</a></li>
    <li class="examples-menu examples-menu-ruby"><a onclick="setExampleLanguage('ruby');">Ruby</a></li>
  </ul>
  <div class="examples-body">
    ```shell
    curl \
      --header "Content-Type: application/json" \
      --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \
      https://app.vagrantup.com/api/v1/box/myuser/test \
      --request PUT \
      --data '
        {
          "box": {
            "name": "test",
            "short_description": "My dev box",
            "description": "My development Vagrant box",
            "is_private": true
          }
        }
      '
    ```


    ```ruby
    # gem install http, or add `gem "http"` to your Gemfile
    require "http"

    api = HTTP.persistent("https://app.vagrantup.com").headers(
      "Content-Type" => "application/json",
      "Authorization" => "Bearer #{ENV['VAGRANT_CLOUD_TOKEN']}"
    )

    response = api.put("/api/v1/box/myuser/test", json: {
      box: {
        name: "test",
        short_description: "My dev box",
        description: "My development Vagrant box",
        is_private: true
      }
    })

    if response.status.success?
      # Success, the response attributes are available here.
      p response.parse
    else
      # Error, inspect the `errors` key for more information.
      p response.code, response.body
    end
    ```
  </div>
</div>

### Delete a box

`DELETE /api/v1/box/:username/:name`

#### Example Request

<div class="examples">
  <ul class="examples-header">
    <li class="examples-menu examples-menu-shell"><a onclick="setExampleLanguage('shell');">cURL</a></li>
    <li class="examples-menu examples-menu-ruby"><a onclick="setExampleLanguage('ruby');">Ruby</a></li>
  </ul>
  <div class="examples-body">
    ```shell
    curl \
      --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \
      --request DELETE \
      https://app.vagrantup.com/api/v1/box/myuser/test
    ```

    ```ruby
    # gem install http, or add `gem "http"` to your Gemfile
    require "http"

    api = HTTP.persistent("https://app.vagrantup.com").headers(
      "Authorization" => "Bearer #{ENV['VAGRANT_CLOUD_TOKEN']}"
    )

    response = api.delete("/api/v1/box/myuser/test")

    if response.status.success?
      # Success, the response attributes are available here.
      p response.parse
    else
      # Error, inspect the `errors` key for more information.
      p response.code, response.body
    end
    ```
  </div>
</div>

#### Example Response

Response body is identical to [Reading a box](#read-a-box).

## Versions

### Read a version

`GET /api/v1/box/:username/:name/version/:version`

#### Example Request

<div class="examples">
  <ul class="examples-header">
    <li class="examples-menu examples-menu-shell"><a onclick="setExampleLanguage('shell');">cURL</a></li>
    <li class="examples-menu examples-menu-ruby"><a onclick="setExampleLanguage('ruby');">Ruby</a></li>
  </ul>
  <div class="examples-body">
    ```shell
    curl \
      --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \
      https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3
    ```

    ```ruby
    # gem install http, or add `gem "http"` to your Gemfile
    require "http"

    api = HTTP.persistent("https://app.vagrantup.com").headers(
      "Authorization" => "Bearer #{ENV['VAGRANT_CLOUD_TOKEN']}"
    )

    response = api.get("/api/v1/box/myuser/test/version/1.2.3")

    if response.status.success?
      # Success, the response attributes are available here.
      p response.parse
    else
      # Error, inspect the `errors` key for more information.
      p response.code, response.body
    end
    ```
  </div>
</div>

#### Example Response

```json
{
  "version": "1.2.3",
  "status": "active",
  "description_html": "<p>A new version</p>\n",
  "description_markdown": "A new version",
  "created_at": "2017-10-20T15:23:17.184Z",
  "updated_at": "2017-10-20T15:23:53.355Z",
  "number": "1.2.3",
  "release_url": "https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3/release",
  "revoke_url": "https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3/revoke",
  "providers": [
    {
      "name": "virtualbox",
      "hosted": false,
      "hosted_token": null,
      "original_url": "https://example.com/virtualbox-1.2.3.box",
      "created_at": "2017-10-20T15:23:35.718Z",
      "updated_at": "2017-10-20T15:23:35.718Z",
      "download_url": "https://vagrantcloud.com/myuser/boxes/test/versions/1.2.3/providers/virtualbox.box"
    }
  ]
}
```

### Create a version

`POST /api/v1/box/:username/:name/versions`

-> New versions start as `unreleased`. You must create a valid provider before releasing a new version.

#### Arguments

* `version`
    * `version` - The version number of this version.
    * `description` - A description for this version. Can be formatted with [Markdown](https://daringfireball.net/projects/markdown/syntax).

#### Example Request

<div class="examples">
  <ul class="examples-header">
    <li class="examples-menu examples-menu-shell"><a onclick="setExampleLanguage('shell');">cURL</a></li>
    <li class="examples-menu examples-menu-ruby"><a onclick="setExampleLanguage('ruby');">Ruby</a></li>
  </ul>
  <div class="examples-body">
    ```shell
    curl \
      --header "Content-Type: application/json" \
      --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \
      https://app.vagrantup.com/api/v1/box/myuser/test/versions \
      --data '
        {
          "version": {
            "version": "1.2.3",
            "description": "A new version"
          }
        }
      '
    ```

    ```ruby
    # gem install http, or add `gem "http"` to your Gemfile
    require "http"

    api = HTTP.persistent("https://app.vagrantup.com").headers(
      "Content-Type" => "application/json",
      "Authorization" => "Bearer #{ENV['VAGRANT_CLOUD_TOKEN']}"
    )

    response = api.post("/api/v1/box/myuser/test/versions", json: {
      version: {
        version: "1.2.3",
        description: "A new version"
      }
    })

    if response.status.success?
      # Success, the response attributes are available here.
      p response.parse
    else
      # Error, inspect the `errors` key for more information.
      p response.code, response.body
    end
    ```
  </div>
</div>

#### Example Response

Response body is identical to [Reading a version](#read-a-version).

### Update a version

`PUT /api/v1/box/:username/:name/version/1.2.3`

#### Arguments

* `version`
    * `version` - The version number of this version.
    * `description` - A description for this version. Can be formatted with [Markdown][markdown].

#### Example Request

<div class="examples">
  <ul class="examples-header">
    <li class="examples-menu examples-menu-shell"><a onclick="setExampleLanguage('shell');">cURL</a></li>
    <li class="examples-menu examples-menu-ruby"><a onclick="setExampleLanguage('ruby');">Ruby</a></li>
  </ul>
  <div class="examples-body">
    ```shell
    curl \
      --header "Content-Type: application/json" \
      --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \
      https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3 \
      --request PUT \
      --data '
        {
          "version": {
            "version": "1.2.3",
            "description": "A new version"
          }
        }
      '
    ```

    ```ruby
    # gem install http, or add `gem "http"` to your Gemfile
    require "http"

    api = HTTP.persistent("https://app.vagrantup.com").headers(
      "Content-Type" => "application/json",
      "Authorization" => "Bearer #{ENV['VAGRANT_CLOUD_TOKEN']}"
    )

    response = api.put("/api/v1/box/myuser/test/version/1.2.3", json: {
      version: {
        name: "1.2.3",
        description: "A new version"
      }
    })

    if response.status.success?
      # Success, the response attributes are available here.
      p response.parse
    else
      # Error, inspect the `errors` key for more information.
      p response.code, response.body
    end
    ```
  </div>
</div>

#### Example Response

Response body is identical to [Reading a version](#read-a-version).

### Delete a version

`DELETE /api/v1/box/:username/:name/version/:version`

#### Example Request

<div class="examples">
  <ul class="examples-header">
    <li class="examples-menu examples-menu-shell"><a onclick="setExampleLanguage('shell');">cURL</a></li>
    <li class="examples-menu examples-menu-ruby"><a onclick="setExampleLanguage('ruby');">Ruby</a></li>
  </ul>
  <div class="examples-body">
    ```shell
    curl \
      --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \
      --request DELETE \
      https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3
    ```

    ```ruby
    # gem install http, or add `gem "http"` to your Gemfile
    require "http"

    api = HTTP.persistent("https://app.vagrantup.com").headers(
      "Authorization" => "Bearer #{ENV['VAGRANT_CLOUD_TOKEN']}"
    )

    response = api.delete("/api/v1/box/myuser/test/version/1.2.3")

    if response.status.success?
      # Success, the response attributes are available here.
      p response.parse
    else
      # Error, inspect the `errors` key for more information.
      p response.code, response.body
    end
    ```
  </div>
</div>

#### Example Response

Response body is identical to [Reading a version](#read-a-version).

### Release a version

`PUT /api/v1/box/:username/:name/version/1.2.3/release`

#### Example Request

<div class="examples">
  <ul class="examples-header">
    <li class="examples-menu examples-menu-shell"><a onclick="setExampleLanguage('shell');">cURL</a></li>
    <li class="examples-menu examples-menu-ruby"><a onclick="setExampleLanguage('ruby');">Ruby</a></li>
  </ul>
  <div class="examples-body">
    ```shell
    curl \
      --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \
      https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3/release \
      --request PUT
    ```

    ```ruby
    # gem install http, or add `gem "http"` to your Gemfile
    require "http"

    api = HTTP.persistent("https://app.vagrantup.com").headers(
      "Authorization" => "Bearer #{ENV['VAGRANT_CLOUD_TOKEN']}"
    )

    response = api.put("/api/v1/box/myuser/test/version/1.2.3/release")

    if response.status.success?
      # Success, the response attributes are available here.
      p response.parse
    else
      # Error, inspect the `errors` key for more information.
      p response.code, response.body
    end
    ```
  </div>
</div>

#### Example Response

Response body is identical to [Reading a version](#read-a-version).

### Revoke a version

`PUT /api/v1/box/:username/:name/version/1.2.3/revoke`

#### Example Request

<div class="examples">
  <ul class="examples-header">
    <li class="examples-menu examples-menu-shell"><a onclick="setExampleLanguage('shell');">cURL</a></li>
    <li class="examples-menu examples-menu-ruby"><a onclick="setExampleLanguage('ruby');">Ruby</a></li>
  </ul>
  <div class="examples-body">
    ```shell
    curl \
      --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \
      https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3/revoke \
      --request PUT
    ```

    ```ruby
    # gem install http, or add `gem "http"` to your Gemfile
    require "http"

    api = HTTP.persistent("https://app.vagrantup.com").headers(
      "Authorization" => "Bearer #{ENV['VAGRANT_CLOUD_TOKEN']}"
    )

    response = api.put("/api/v1/box/myuser/test/version/1.2.3/revoke")

    if response.status.success?
      # Success, the response attributes are available here.
      p response.parse
    else
      # Error, inspect the `errors` key for more information.
      p response.code, response.body
    end
    ```
  </div>
</div>

#### Example Response

Response body is identical to [Reading a version](#read-a-version).

## Providers

### Read a provider

`GET /api/v1/box/:username/:name/version/:version/provider/:provider`

#### Example Request

<div class="examples">
  <ul class="examples-header">
    <li class="examples-menu examples-menu-shell"><a onclick="setExampleLanguage('shell');">cURL</a></li>
    <li class="examples-menu examples-menu-ruby"><a onclick="setExampleLanguage('ruby');">Ruby</a></li>
  </ul>
  <div class="examples-body">
    ```shell
    curl \
      --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \
      https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3/provider/virtualbox
    ```

    ```ruby
    # gem install http, or add `gem "http"` to your Gemfile
    require "http"

    api = HTTP.persistent("https://app.vagrantup.com").headers(
      "Authorization" => "Bearer #{ENV['VAGRANT_CLOUD_TOKEN']}"
    )

    response = api.get("/api/v1/box/myuser/test/version/1.2.3/provider/virtualbox")

    if response.status.success?
      # Success, the response attributes are available here.
      p response.parse
    else
      # Error, inspect the `errors` key for more information.
      p response.code, response.body
    end
    ```
  </div>
</div>


#### Example Response

```json
{
  "name": "virtualbox",
  "hosted": false,
  "hosted_token": null,
  "original_url": "https://example.com/virtualbox-1.2.3.box",
  "created_at": "2017-10-20T15:23:35.718Z",
  "updated_at": "2017-10-20T15:23:35.718Z",
  "download_url": "https://vagrantcloud.com/myuser/boxes/test/versions/1.2.3/providers/virtualbox.box"
}
```

### Create a provider

`POST /api/v1/box/:username/:name/version/:version/providers`

#### Arguments

* `provider`
    * `name` - The name of the provider.
    * `url` - A valid URL to download this provider. If omitted, you must [upload](#upload-a-provider) the Vagrant box image for this provider to Vagrant Cloud before the provider can be used.

#### Example Request

<div class="examples">
  <ul class="examples-header">
    <li class="examples-menu examples-menu-shell"><a onclick="setExampleLanguage('shell');">cURL</a></li>
    <li class="examples-menu examples-menu-ruby"><a onclick="setExampleLanguage('ruby');">Ruby</a></li>
  </ul>
  <div class="examples-body">
    ```shell
    curl \
      --header "Content-Type: application/json" \
      --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \
      https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3/providers \
      --data '
        {
          "provider": {
            "name": "virtualbox",
            "url": "https://example.com/virtualbox-1.2.3.box"
          }
        }
      '
    ```

    ```ruby
    # gem install http, or add `gem "http"` to your Gemfile
    require "http"

    api = HTTP.persistent("https://app.vagrantup.com").headers(
      "Content-Type" => "application/json",
      "Authorization" => "Bearer #{ENV['VAGRANT_CLOUD_TOKEN']}"
    )

    response = api.post("/api/v1/box/myuser/test/version/1.2.3/providers", json: {
      provider: {
        name: "virtualbox",
        url: "https://example.com/virtualbox-1.2.3.box"
      }
    })

    if response.status.success?
      # Success, the response attributes are available here.
      p response.parse
    else
      # Error, inspect the `errors` key for more information.
      p response.code, response.body
    end
    ```
  </div>
</div>

#### Example Response

Response body is identical to [Reading a provider](#read-a-provider).

### Update a provider

`PUT /api/v1/box/:username/:name/version/:version/provider/:provider`

#### Arguments

* `provider`
    * `name` - The name of the provider.
    * `url` - A valid URL to download this provider. If omitted, you must [upload](#upload-a-provider) the Vagrant box image for this provider to Vagrant Cloud before the provider can be used.

#### Example Request

<div class="examples">
  <ul class="examples-header">
    <li class="examples-menu examples-menu-shell"><a onclick="setExampleLanguage('shell');">cURL</a></li>
    <li class="examples-menu examples-menu-ruby"><a onclick="setExampleLanguage('ruby');">Ruby</a></li>
  </ul>
  <div class="examples-body">
    ```shell
    curl \
      --header "Content-Type: application/json" \
      --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \
      https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3/provider/virtualbox \
      --request PUT \
      --data '
        {
          "provider": {
            "name": "virtualbox",
            "url": "https://example.com/virtualbox-1.2.3.box"
          }
        }
      '
    ```

    ```ruby
    # gem install http, or add `gem "http"` to your Gemfile
    require "http"

    api = HTTP.persistent("https://app.vagrantup.com").headers(
      "Content-Type" => "application/json",
      "Authorization" => "Bearer #{ENV['VAGRANT_CLOUD_TOKEN']}"
    )

    response = api.put("/api/v1/box/myuser/test/version/1.2.3/provider/virtualbox", json: {
      provider: {
        name: "virtualbox",
        url: "https://example.com/virtualbox-1.2.3.box"
      }
    })

    if response.status.success?
      # Success, the response attributes are available here.
      p response.parse
    else
      # Error, inspect the `errors` key for more information.
      p response.code, response.body
    end
    ```
  </div>
</div>

#### Example Response

Response body is identical to [Reading a provider](#read-a-provider).

### Delete a provider

`DELETE /api/v1/box/:username/:name/version/:version/provider/:provider`

#### Example Request

<div class="examples">
  <ul class="examples-header">
    <li class="examples-menu examples-menu-shell"><a onclick="setExampleLanguage('shell');">cURL</a></li>
    <li class="examples-menu examples-menu-ruby"><a onclick="setExampleLanguage('ruby');">Ruby</a></li>
  </ul>
  <div class="examples-body">
    ```shell
    curl \
      --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \
      --request DELETE \
      https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3/provider/virtualbox
    ```

    ```ruby
    # gem install http, or add `gem "http"` to your Gemfile
    require "http"

    api = HTTP.persistent("https://app.vagrantup.com").headers(
      "Authorization" => "Bearer #{ENV['VAGRANT_CLOUD_TOKEN']}"
    )

    response = api.delete("/api/v1/box/myuser/test/version/1.2.3/provider/virtualbox")

    if response.status.success?
      # Success, the response attributes are available here.
      p response.parse
    else
      # Error, inspect the `errors` key for more information.
      p response.code, response.body
    end
    ```
  </div>
</div>

#### Example Response

Response body is identical to [Reading a provider](#read-a-provider).

### Upload a provider

`GET /api/v1/box/:username/:name/version/:version/provider/:provider/upload`

Prepares the provider for upload, and returns a JSON blob containing an `upload_path`.

~> The upload must begin shortly after the response is returned, otherwise the URL will expire. If the URL expires, you can request this same API method again for a new upload URL.

#### Example Request

<div class="examples">
  <ul class="examples-header">
    <li class="examples-menu examples-menu-shell"><a onclick="setExampleLanguage('shell');">cURL</a></li>
    <li class="examples-menu examples-menu-ruby"><a onclick="setExampleLanguage('ruby');">Ruby</a></li>
  </ul>
  <div class="examples-body">
    ```shell
    response=$(curl \
      --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \
      https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3/provider/virtualbox/upload)

    # Requires the jq command
    upload_path=$(echo "$response" | jq .upload_path)

    curl \
      $upload_path \
      --request PUT \
      --upload-file virtualbox-1.2.3.box
    ```

    ```ruby
    # gem install http, or add `gem "http"` to your Gemfile
    require "http"

    api = HTTP.persistent("https://app.vagrantup.com").headers(
      "Authorization" => "Bearer #{ENV['VAGRANT_CLOUD_TOKEN']}"
    )

    response = api.get("/api/v1/box/myuser/test/version/1.2.3/provider/virtualbox/upload")

    if response.status.success?
      # Success, you can now upload the box image to the returned URL
      upload_path = response.parse['upload_path']
      HTTP.post upload_path, body: File.open("virtualbox-1.2.3.box")
    else
      # Error, inspect the `errors` key for more information.
      p response.code, response.body
    end
    ```
  </div>
</div>

#### Example Response

```json
{
  "upload_path": "https://archivist.hashicorp.com/v1/object/630e42d9-2364-2412-4121-18266770468e"
}
```

[markdown]: https://daringfireball.net/projects/markdown/syntax
